package oop.ex1.filters;
import java.io.*;
import java.util.*;
import java.text.*;

import oop.ex1.filters.YesNoException;



/**this class contains all filters described in the exercise.
 * @author miron_6 & dawn16889
 *
 */
public class Filters{

	
	/**this method parses String to date.
	 * @param dateStr - the String to parse into date.
	 * @return date - the parsed String.
	 * @throws IllegalDateException - if date is illegal.
	 */
	public static Date dateConvStr(String dateStr) throws IllegalDateException{
		Date d = null;
		try {
			//setting a SimpleDateFormat param to Date param from the given String.
			SimpleDateFormat temp= new SimpleDateFormat("dd/MM/yyyy");
			d= temp.parse(dateStr);
		//tries to catch ParseException in order to throw IllegalDateException.
		} catch (ParseException e) {
			throw new IllegalDateException(e.getMessage(), e.getErrorOffset());
		}
		return d;
	}
	
	/**this method parses long to date.
	 * @param x - the long to parse into date.
	 * @return date - the parsed long.
	 */
	public static Date dateConveLong(long x){
		return new Date(x);
	}

	/**This method gets a string 
	 * @param yesNo - String containing YES or NO.
	 * @return - true if the String is YES, false for NO. 
	 * @throws YesNoException - if the given String in neither YES nor NO. 
	 */
	public static boolean yesNoBool(String yesNo) throws YesNoException {
		if (yesNo.equals("YES"))
			return true;
		if (yesNo.equals("NO"))
			return false;
		else{ //if the given String in neither YES nor NO.
			throw new YesNoException();
		}
	}
	
	/**this class returns the Files modified before (including) the given date.
	 * @author miron_6 & dawn16889
	 */
	public static class Before implements FileFilter {
		
		
		/**
		 * date param to use in those methods 
		 */
		private Date date; 
		
		/**class constructor.
		 * @param dateStr - represent the date limit.
		 * @throws IllegalDateException - if date is illegal.
		 */
		public Before(String dateStr) throws IllegalDateException{
			try {
				this.date = dateConvStr(dateStr);
			}
			catch (ParseException e) { //if date is illegal
				throw new IllegalDateException(e.getMessage(),e.getErrorOffset());
			}
		}
		
		//implementing the accept method from FileFilter interface.
		public boolean accept (File pathname){
			//setting a date param from  file's lastModified date.
			Date temp = dateConveLong(pathname.lastModified());
			return (temp.before(date) || temp.equals(date));
		}
	
	}
	
	/**this class returns the Files modified after (including) the given date
	 * @author miron_6 & dawn16889
	 *
	 */
	public static class After implements FileFilter {
		
		private Date date; 
		
		/**class constructor.
		 * @param dateStr - represent the date limit.
		 * @throws IllegalDateException - if date is illegal.
		 */
		public After (String dateStr) throws IllegalDateException {
			try{
				this.date = dateConvStr(dateStr);
			} 
			catch (ParseException e) {
				throw new IllegalDateException(e.getMessage(),e.getErrorOffset());
			}
		}
		
		//implementing the accept method from FileFilter interface.
		public boolean accept (File pathname){
			//setting a date param from  file's lastModified date.
			Date temp = dateConveLong(pathname.lastModified());
			return (temp.after(date) || temp.equals(date));
		}
	
	}
	/**
	 * this class returns the Files who's size is more than the given number of k-bytes.
	 * @author miron_6 & dawn16889
	 *
	 */
	public static class GreaterThan implements FileFilter {
		
		private double size;
		
		/**class constructor
		 * @param size - String represents the size limit.
		 */
		public GreaterThan(String size){
			this.size= Double.valueOf(size);
		}
		
		//implementing the accept method from FileFilter interface.
		public boolean accept (File pathname){
			if (this.size*128 < pathname.length())
				return true;
			return false;
		}
		
	}
	/**
	 * this class returns the Files who's size is less than the given number of k-bytes.
	 * @author miron_6 & dawn16889
	 *
	 */
	public static class SmallerThan implements FileFilter{
		private double size;
		
		/**class constructor
		 * @param size -represents the size limit
		 */
		public SmallerThan(String size){
			this.size= Double.valueOf(size);
		}
		
		//implementing the accept method from FileFilter interface.
		public boolean accept (File pathname){
			if (this.size*128 > pathname.length())
				return true;
			return false;
		}

	}
	
	/**this class returns the files who's string equals the file name (excluding path)
	 * @author miron_6 & dawn16889
	 *
	 */
	public static class FileName implements FileFilter{
		
		private String name;
		/**class constructor
		 * @param name - the string to compare
		 */
		public FileName (String name){
			this.name=name;
		}
		
		//implementing the accept method from FileFilter interface.
		public boolean accept (File pathname){
			if ((pathname.getName().toUpperCase()).equals(name.toUpperCase()))
				return true;
			return false;
		}
	}
	
	/**this class returns the files who's string is the prefix of the file name (excluding path)
	 * @author miron_6 & dawn16889
	 *
	 */
	public static class Prefix implements FileFilter{
		
		private String pref;
		/**class constructor
		 * @param pref - the prefix string
		 */
		public Prefix (String pref){
			this.pref=pref;
		}
		
		//implementing the accept method from FileFilter interface.
		public boolean accept (File pathname){
			if (pathname.getName().startsWith(pref))
				return true;
			return false;
		}
	}
	
	/**this class returns the files who's string is the prefix of the file name (excluding path)
	 * @author miron_6 & dawn16889
	 *
	 */
	public static class Suffix implements FileFilter{
		
		private String suff;
		/**class constructor
		 * @param suff - the suffix string
		 */
		public Suffix (String suff){
			this.suff=suff;
		}
		
		//implementing the accept method from FileFilter interface.
		public boolean accept (File pathname){
			if (pathname.getName().endsWith(suff))
				return true;
			return false;
		}
	}
	
	/**this class returns the files that do or don't have writing permission accordingly
	 * @author miron_6 & dawn16889
	 *
	 */
	public static class Writable implements FileFilter{
		
		boolean write;
		/**class constructor
		 * @param write - indicates whether or not writing permission is needed 
		 * @throws YesNoException - if the given String in neither YES nor NO.
		 */
		public Writable(String write) throws YesNoException{
			this.write=yesNoBool(write);
		}
		
		//implementing the accept method from FileFilter interface.
		public boolean accept (File pathname){
			if (write == true)
				return pathname.canWrite();
			return !pathname.canWrite();
		}
	}
	
	/**this class returns the files that do or don't have execution permission accordingly
	 * @author miron_6 & dawn16889
	 *
	 */
	public static class Executable implements FileFilter{
		
		boolean execut;
		
		/**class constructor
		 * @param execut - indicates whether or not execution permission is needed
		 * @throws YesNoException - if the given String in neither YES nor NO. 
		 */
		public Executable (String execut) throws YesNoException{
			this.execut=yesNoBool(execut);
		}
		
		//implementing the accept method from FileFilter interface.
		public boolean accept (File pathname){
			return (execut==pathname.canExecute())? true:false;
		}
	}
	
	/**this class returns the files that are or arn't hidden
	 * @author miron_6 & dawn16889
	 *
	 */
	public static class Hidden implements FileFilter{
		
		boolean hidd;
		
		/**class constructor
		 * @param hidd - indicates if we're looking for a hidden file or not
		 * @throws YesNoException - if the given String in neither YES nor NO.
		 */
		public Hidden (String hidd) throws YesNoException{
			this.hidd=yesNoBool(hidd);
			
		}
		
		//implementing the accept method from FileFilter interface.
		public boolean accept (File pathname){
			return (hidd==pathname.isHidden())? true:false;
		}
	}
	
	
	
}
